-----------------------------------------------------------------------------
-- The msl_router:                                                         --
--  Designed by Dobkin Rostislav(Reuven).                                  --
--  Date : 09.2004                                                         --
--  Last edit : 14.09.2004                                                 --
-----------------------------------------------------------------------------
-- Multi-Service Router                                                    --
-----------------------------------------------------------------------------

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_arith.all;
    use ieee.std_logic_unsigned.all;
    
library work;
    use work.router_pack.all;

------------------------------------------------------------------------- 
entity msl_router is
------------------------------------------------------------------------- 
port(
       -- General Signlas: --
       RESET           : in  std_logic; 
       
       -- Input Ports i/f: --
       RI              : in  std_logic_vector(num_of_ports_con downto 0);
       AI              : out std_logic_vector(num_of_ports_con downto 0);
       DI              : in  msl_router_mult_ports_data_bus_type;
       
       -- Output Ports i/f: --
       RO              : out std_logic_vector(num_of_ports_con downto 0);
       AO              : in  std_logic_vector(num_of_ports_con downto 0);
       DO              : out msl_router_mult_ports_data_bus_type
    );  
------------------------------------------------------------------------- 
end msl_router;
------------------------------------------------------------------------- 

------------------------------------------------------------------------- 
architecture msl_router_arch of msl_router is
------------------------------------------------------------------------- 

component msl_ip
port( 
      -- General Control: --
      RESET     : in  std_logic;  -- Active  

      -- External input i/f: --
      RI        : in  std_logic;
      AI        : out std_logic;
      DATAI     : in  std_logic_vector(vc_width+msl_ind_width+flit_width_con-1 downto 0);

      -- Internal output i/f: --
      RO_H_ARR  : out signaling_msl_bus_type;  -- SL x VC x NumOfPorts
      RO_BT_ARR : out signaling_msl_bus_type;  -- SL x VC x NumOfPorts -- BT can be also broadcasted as DATA!
      AO_ARR    : in  signaling_msl_bus_type;  -- SL x VC x NumOfPorts -- Acknowelege can be ORed sinceonly one OP will return acknowelege to the certain VC.

      DO        : out data_msl_bus_type        -- SL x VC x flit_width (the data is connected directly to all OP-VCs)
);           
end component;

component msl_op
port( 
      -- General Control: --
      RESET     : in  std_logic;  -- Active Low 

      -- Internal Interface: --
      RH_ARR    : in  signaling_msl_bus_type;          -- pulse valid to OP .
      RBT_ARR   : in  signaling_msl_bus_type;          -- pulse valid to OP .
      DI        : in  data_msl_op_bus_type;            -- Busses from all IPs x SL x VC.
      AI_ARR    : out signaling_msl_bus_type;          -- Acknoweledge to all OPs (arr -- SLs).       

      -- External Interface: --
      RO        : out std_logic;
      AO        : in  std_logic;
      DO        : out std_logic_vector(vc_width+msl_ind_width+flit_width_con-1 downto 0)
);           
end component;

type   interconnect_req_out_ip_type is array (0 to num_of_ports_con) of signaling_msl_bus_type;
signal interconnect_ro_h_ip  : interconnect_req_out_ip_type; -- all ports x SL x VC x NumOfPorts
signal interconnect_ro_bt_ip : interconnect_req_out_ip_type;

signal interconnect_ro_h_op  : interconnect_req_out_ip_type;
signal interconnect_ro_bt_op : interconnect_req_out_ip_type;

signal interconnect_vout_ip : interconnect_req_out_ip_type;
signal interconnect_vin_op  : interconnect_req_out_ip_type;

type   data_int_bus_type         is array (0 to num_of_ports_con) of data_msl_bus_type;
signal data_int_bus         : data_int_bus_type;

type   data_to_op_bus_type       is array (0 to num_of_ports_con) of data_msl_op_bus_type;
signal data_to_op_bus       : data_to_op_bus_type;

type   ack_to_ip_type            is array (0 to num_of_ports_con) of std_logic_vector(num_of_sl_con-1 downto 0);
signal ack_to_ip            : ack_to_ip_type;

signal ack_from_op          : interconnect_req_out_ip_type;
signal ack_to_ip_vec        : interconnect_req_out_ip_type;

begin

ip_op_gen: for i in 0 to num_of_ports_con generate

  u_msl_ip: msl_ip
  port map( 
      RESET     => RESET,  -- Active  High

      RI        => RI(i),
      AI        => AI(i),
      DATAI     => DI(i),

      RO_H_ARR  => interconnect_ro_h_ip(i),
      RO_BT_ARR => interconnect_ro_bt_ip(i),
      AO_ARR    => ack_to_ip_vec(i),        --ack_to_ip(i),

      DO        => data_int_bus(i)
  );


  u_msl_op: msl_op
  port map( 
      RESET     => RESET,  -- Active High 

      RH_ARR    => interconnect_ro_h_op(i),               -- pulse valid to OP .
      RBT_ARR   => interconnect_ro_bt_op(i),              -- pulse valid to OP .
      DI        => data_to_op_bus(i),                     -- shared bus to all OPs.
      AI_ARR    => ack_from_op(i),                        -- Acknoweledge to all OPs (arr -- SLs).       

      RO        => RO(i),
      AO        => AO(i),
      DO        => DO(i)
  );

 
 interconnect_proc: process(interconnect_ro_h_ip, interconnect_ro_bt_ip, data_int_bus, ack_from_op) 
 begin
  -- for the given output port i do: --
   
  for j in 0 to num_of_ports_con loop     -- loop on all connected input ports
   
   for sl in 0 to (num_of_sl_con-1) loop  -- service level loop.
    
    for vc in 0 to (num_of_vc_con-1) loop  -- virtual channel loop.

     if (j < i) then 
      -- For given OP=i --(OP)(SL)(VC)(IP) -- here "(VC)(IP)" refer to the all VCs in all IPs.
      interconnect_ro_h_op(i)(sl)(vc)(j)  <= interconnect_ro_h_ip(j)(sl)(vc)(i-1);
      interconnect_ro_bt_op(i)(sl)(vc)(j) <= interconnect_ro_bt_ip(j)(sl)(vc)(i-1);

                  --(OP)(IP)(SL)(VC)                  -- (IP)(SL)(VC)
      data_to_op_bus(i)(j)(sl)(vc)        <= data_int_bus(j)(sl)(vc);
      ack_to_ip_vec(i)(sl)(vc)(j)         <= ack_from_op(j)(sl)(vc)(i-1); --the acknowelege is return separtely to each VC in each IP
     
     elsif (j > i) then 
      interconnect_ro_h_op(i)(sl)(vc)(j-1)  <= interconnect_ro_h_ip(j)(sl)(vc)(i);
      interconnect_ro_bt_op(i)(sl)(vc)(j-1) <= interconnect_ro_bt_ip(j)(sl)(vc)(i);

      data_to_op_bus(i)(j-1)(sl)(vc)        <= data_int_bus(j)(sl)(vc);
      ack_to_ip_vec(i)(sl)(vc)(j-1)         <= ack_from_op(j)(sl)(vc)(i);
     end if;
     
    end loop; -- vc
   end loop;  -- sl

  end loop;   -- j 
    
 end process; -- interconnect_proc
  
end generate; -- i

------------------------------------------------------------------------- 
end msl_router_arch;
-------------------------------------------------------------------------

------------------------------------------------------------------------- 
configuration msl_router_cfg of msl_router is
------------------------------------------------------------------------- 
   for msl_router_arch
   end for;
------------------------------------------------------------------------- 
end msl_router_cfg;
-------------------------------------------------------------------------
